/**
 * Invoice class gives invoice details
 */
package docoffice.doss;

import java.sql.ResultSet;
import java.util.logging.Logger;

import docoffice.database.DatabaseManager;
import docoffice.doss.Patient.insuranceCarrier;

/**
 * @author Ray Nosari
 * @version $Revision 1.0
 */
public class Invoice {

	/**
	 * Field appt.
	 */
	private Appointment appointment;
	
	/**
	 * Field BASE_FEE.
	 * (value is 75)
	 */
	private static final int BASE_FEE = 75;
	
	/**
	 * Field NO_COVERAGE.
	 * (value is 0.0)
	 */
	private static final double NO_COVERAGE = 0;
	
	/**
	 * Field GOOD_COVERAGE.
	 * (value is 0.5)
	 */
	private static final double GOOD_COVERAGE = .5;
	
	/**
	 * Field BETTER_COVERAGE.
	 * (value is 0.7)
	 */
	private static final double BETTER_COVERAGE = .7;
	
	/**
	 * Field BEST_COVERAGE.
	 * (value is 0.9)
	 */
	private static final double BEST_COVERAGE = .9;
	
	/**
	 * Field id;
	 */
	private int id;
	
	/**
	 * Field LOG. 
	 */
	private static final Logger LOG = Logger.getLogger("Invoice");
	
	/**
	 * Constructor for Invoice.
	 * @param appt Appointment
	 */
	public Invoice(Appointment appt){
		this.appointment = appt;
	}
	
	
	/**
	 * Method toString.
	
	 * @return String */
	@Override
	public String toString() {
		return "Invoice [appointment=" + appointment + "]";
	}

	/**
	 * Method getAppointment.
	
	 * @return Appointment */
	public Appointment getAppointment(){
		return this.appointment;
	}
	
	/**
	 * Method setAppointment.
	 * @param appt Appointment
	 */
	public void setAppointment(Appointment appt){
		this.appointment = appt;
	}
	
	/**
	 * Method createInvoice.
	 */
	public void createInvoice(){
		final Patient patient = this.appointment.getPatient();
		final int patientId = patient.readPatientID();
		final Appointment appointment = this.appointment;
		final int appointmentId = appointment.readAppointmentId(appointment);
		final String invoiceDate =  appointment.getDate();
		final DatabaseManager dbMgr = new DatabaseManager();
		final String sqlQuery = "INSERT INTO invoice (PatientID, InvoiceDate, AppointmentID) VALUES (" + 
		        patientId + ", " + invoiceDate + ", " + appointmentId + ")";
		System.out.println(sqlQuery);
		try{
			dbMgr.runUpdateQuery(sqlQuery);
		} catch(Exception e){
			LOG.severe("A SQL Error occurred while creating invoice");
			e.printStackTrace();
		} finally{
			dbMgr.closeConnection();
		}
		
		LOG.info("Invoice successfully created");
	}
	
	/**
	 * Method readInvoice
	 * @param invoice
	 * @return invoice
	 */
	public Invoice readInvoice(Invoice invoice){
		final int invoiceId = invoice.readInvoiceID();
		final DatabaseManager dbMgr = new DatabaseManager();
		final String sqlQuery = "SELECT * FROM invoice WHERE InvoiceID = " + invoiceId;
		ResultSet rs = null;
		
		try{
			rs = dbMgr.runReadQuery(sqlQuery);
			if (rs.first()){
				final int appointmentId = rs.getInt("AppointmentID");
				Appointment appointment = new Appointment("", "", "", null);
				appointment.setId(appointmentId);
				appointment = appointment.readAppointment(appointment);
				invoice.setAppointment(appointment);
			}
		} catch(Exception e){
			LOG.severe("A SQL Error occurred while reading invoice");
			e.printStackTrace();
		} finally{
			dbMgr.closeConnection(rs);
		}
		return invoice;
	}
	
	public int readInvoiceID(){
		int id = 0;
		final Patient patient = this.appointment.getPatient();
		final int patientId = patient.getId();
		final String invoiceDate = this.appointment.getDate();
		final int appointmentId = this.appointment.getId();
		final DatabaseManager dbMgr = new DatabaseManager();
		final String sqlQuery = "SELECT InvoiceID FROM invoice WHERE PatientID = " +
		        patientId + " AND InvoiceDate = " + invoiceDate + " AND AppointmentID = "
		        + appointmentId;
		ResultSet rs = null;
		
		try{
			rs = dbMgr.runReadQuery(sqlQuery);
			if (rs.first()){
				id = rs.getInt("InvoiceID");
				this.id = id;
			}
		} catch(Exception e){
			LOG.severe("A SQL Error occurred while reading invoice");
			e.printStackTrace();
		} finally{
			dbMgr.closeConnection(rs);
		}
		
		return id;
	}
	
	public void updateInvoice(){
		final Patient patient = this.appointment.getPatient();
		final int patientId = patient.getId();
		final String invoiceDate = this.appointment.getDate();
		final int appointmentId = this.appointment.getId();
		final int invoiceId = this.id;
		final DatabaseManager dbMgr = new DatabaseManager();
		final String sqlQuery = "UPDATE invoice SET PatientID = " + 
		        patientId + ", InvoiceDate = " + invoiceDate + 
		        ", AppointmentID = " + appointmentId + " WHERE InvoiceID = "
		        + invoiceId;
		try{
			dbMgr.runUpdateQuery(sqlQuery);
		} catch(Exception e){
			LOG.severe("A SQL Error occurred while updating invoice");
			e.printStackTrace();
		} finally{
			dbMgr.closeConnection();
		}
		
		LOG.info("Invoice successfully updated");
	}
	
	public void deleteInvoice(){
		final int invoiceId = this.id;
		final DatabaseManager dbMgr = new DatabaseManager();
		final String sqlQuery = "DELETE FROM invoice WHERE InvoiceId = " + invoiceId;
		
		try{
			dbMgr.runUpdateQuery(sqlQuery);
		} catch(Exception e){
			LOG.severe("A SQL Error occurred while deleting invoice");
			e.printStackTrace();
		} finally{
			dbMgr.closeConnection();
		}
		
		LOG.info("Invoice successfully deleted");
	}
	
	/**
	 * Method findCoverage.
	 * @param insurance String
	 * @return double
	 */
	public double findCoverage(insuranceCarrier insurance){
		double coverage = NO_COVERAGE;
		if (insurance == insuranceCarrier.GOOD){
			coverage = GOOD_COVERAGE;
		}
		else if (insurance == insuranceCarrier.BETTER){
			coverage = BETTER_COVERAGE;
		} 
		else if (insurance == insuranceCarrier.BEST){
			coverage = BEST_COVERAGE;
		}
		return coverage;
	}
	
	public int getId(){
		return this.id;
	}
	
	public void setId(int id){
		this.id = id;
	}
	
	public double totalBill(){
		double  total = 0;
		final Patient patient = this.appointment.getPatient();
		final insuranceCarrier insurance = patient.getInsuranceCarrier();
		final double coverage = findCoverage(insurance);
		final TreatmentRec treatment = this.appointment.getTreatment();
		final DocOrders orders = treatment.getTreatOrders();
		final LabWork labwork = orders.getLabWork();
		final double labcost = labwork.getCost();
		total = (BASE_FEE + labcost) * (1 - coverage);
		total = total*100.00;
		total = Math.round(total);
		total = total/100.00;
		return total;
	}
}
